package cc.minos.components.scrollbar
{
	import caurina.transitions.Tweener;
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	
	/**
	 * ...
	 * @version 2013/03/13 9:36
	 * @since 2012/
	 * @author Minos
	 */
	public class ScrollBar extends Sprite
	{
		public static const HORIZONTAL:String = "scrollHorizontal";
		public static const VERTICAL:String = "scrollVertical";
		
		//目标移动速度
		public var speed:Number = .5;
		//移动缓冲
		public var ease:String = "easeOutQuint";
		//拖动条长度
		public var sizeRatio:Object = "auto";
		//自动滚动
		private var _autoScroll:Boolean = true;
		//private var _scrollAble:Boolean = true;
		
		private var area:Rectangle;
		private var _target:*;
		private var _direction:String;
		private var offset:Number;
		
		private var timerScroll:Timer;
		private var scrollSign:Number = 1;
		private var _scrollIncrement:Number = 10;
		private var dispatcherToMute:EventDispatcher;
		private var isReady:Boolean = false;
		
		private const DEFAUT_FREQUENCY:Number = 5;
		private const INIT_TIME:Number = 0;
		
		protected var thumb:DisplayObject;
		protected var track:DisplayObject;
		protected var btnUp:DisplayObject;
		protected var btnDown:DisplayObject;
		
		public function ScrollBar( skin:Object = null ):void
		{
			if ( skin )
			{
				thumb = skin["thumb"];
				track = skin["track"];
				btnUp = skin["btnUp"];
				btnDown = skin["btnDown"];
				addChild( skin as DisplayObject );
			}
			
			area = track.getBounds( this );
			area.width = 0;
			
			area.height -= thumb.height;
			thumb.y = area.y;
			
			direction = VERTICAL;
			
			track.addEventListener( MouseEvent.MOUSE_DOWN , onTrackDown );
			thumb.addEventListener( MouseEvent.MOUSE_DOWN , onThumbDown );
			addEventListener( MouseEvent.MOUSE_WHEEL , onMouseWheel );
			
			timerScroll = new Timer( 1000 / DEFAUT_FREQUENCY , 0 );
			timerScroll.addEventListener( TimerEvent.TIMER , onTimerTick );
			btnUp.addEventListener( MouseEvent.MOUSE_DOWN , onBtnUpDown );
			btnDown.addEventListener( MouseEvent.MOUSE_DOWN , onBtnDownDown );
			
			addEventListener( Event.SCROLL , onScroll );
		}
		
		/**
		 * 百分比
		 */
		public function get scrollRatio():Number
		{
			return area.height == 0 ? 0 : ( thumb.y - area.y ) / area.height;
		}
		
		public function set scrollRatio( ratio:Number ):void
		{
			dispatcherToMute.removeEventListener( Event.SCROLL , onScroll );
			thumb.y = (( isNaN( ratio ) || !isFinite( ratio ) ) ? 0 : ratio ) * area.height + area.y;
			dispatchEvent( new Event( Event.SCROLL ) );
			dispatcherToMute.addEventListener( Event.SCROLL , onScroll );
		}
		
		/**
		 * 百分比
		 * @param	ratio
		 * @param	source
		 */
		protected function setScrollRatio( ratio:Number , source:EventDispatcher = null ):void
		{
			dispatcherToMute = (source == null) ? target: this;
			
			if ( ratio < 0.001 )
				ratio = 0;
			else if ( ratio > 0.990 )
				ratio = 1;
			
			Tweener.addTween( this , { time: speed , scrollRatio: ratio , transition: ease } );
		}
		
		/*		2012/10/16 +auto scroll		*/
		
		protected var tempRatio:Number = 1;
		
		public function get autoScroll():Boolean
		{
			return _autoScroll;
		}
		
		public function set autoScroll( b:Boolean ):void
		{
			_autoScroll = b;
		}
		
		public function scrollToStart():void
		{
			setScrollRatio( 0 );
		}
		
		public function scrollToEnd():void
		{
			setScrollRatio( 1 );
		}
		
		/**
		 * 移动百分比
		 */
		public function get scrollIncrement():Object
		{
			return _scrollIncrement * ( direction == VERTICAL ? target.maxScrollV - 1 : target.maxScrollH ) / 100;
		
		}
		
		public function set scrollIncrement( v:Object ):void
		{
			if ( isReady )
				setScrollIncrement( v );
			else
			{
				var timer:Timer = new Timer( INIT_TIME , 1 );
				timer.addEventListener( TimerEvent.TIMER , function():void
					{
						setScrollIncrement( v );
					} );
				timer.start();
			}
		}
		
		private function setScrollIncrement( v:Object ):void
		{
			if ( v is String || v is Number )
			{
				_scrollIncrement = 0;
				_scrollIncrement = Number( v ) / ( v is String ? 100 : ( direction == VERTICAL ? target.maxScrollV - 1 : target.maxScrollH ) );
				
				if ( _scrollIncrement > 1 )
					_scrollIncrement = 1;
				
				_scrollIncrement *= 100;
			}
		}
		
		/**
		 * 频率
		 */
		public function get scrollFrequency():Number
		{
			return 1000 / timerScroll.delay;
		}
		
		/**
		 * 设置移动频率
		 * @param	f	:	一秒移动的次数
		 */
		public function set scrollFrequency( f:Number ):void
		{
			timerScroll.delay = 1000 / f;
		}
		
		/**
		 * 方向类型
		 */
		public function get direction():String
		{
			return _direction;
		}
		
		/**
		 * 设置方向类型
		 * @param	dir	:	VERTICAL || HORIZONTAL
		 */
		public function set direction( dir:String ):void
		{
			_direction = dir;
			
			if ( target != null )
			{
				if ( dir == VERTICAL )
					_target.addEventListener( MouseEvent.MOUSE_WHEEL , onMouseWheel );
				else
					_target.removeEventListener( MouseEvent.MOUSE_WHEEL , onMouseWheel );
			}
		}
		
		/**
		 * 获取目标
		 */
		public function get target():*
		{
			return _target;
		}
		
		/**
		 * 设置目标
		 * @param object	:	IScrollAbleV || IScrollAbleH
		 */
		public function set target( object:* ):void
		{
			
			if ( target != null )
			{
				target.removeEventListener( Event.CHANGE , onTargetContentChange );
				target.removeEventListener( Event.SCROLL , onScroll );
			}
			
			if ( object is IScrollAbleV || object is IScrollAbleH )
			{
				_target = object;
				isReady = false;
				
				_target.addEventListener( Event.CHANGE , onTargetContentChange );
				_target.addEventListener( Event.SCROLL , onScroll );
				
				var timer:Timer = new Timer( INIT_TIME , 1 );
				timer.addEventListener( TimerEvent.TIMER , function():void
					{
						isReady = true;
						setSize( sizeRatio );
					} );
				
				timer.start();
			}
		
		}
		
		/**
		 *
		 */
		public function get size():Object
		{
			return 100 * thumb.height / track.height;
		}
		
		/**
		 *
		 */
		public function set size( val:Object ):void
		{
			if ( isReady )
				setSize( val );
			else
			{
				var timer:Timer = new Timer( INIT_TIME , 1 );
				timer.addEventListener( TimerEvent.TIMER , function():void
					{
						setSize( val );
					} );
				timer.start();
			}
		
		}
		
		protected function setSize( val:Object ):void
		{
			var adjustedHeight:Number = track.height;
			sizeRatio = val;
			if ( val == "auto" )
			{
				adjustedHeight = track.height * ( direction == VERTICAL ? ( target.contentHeight - ( target.maxScrollV - 1 ) ) / target.contentHeight : ( target.contentWidth - target.maxScrollH ) / target.contentWidth );
			}
			else if ( val is Number && (( direction == VERTICAL && target.maxScrollV > 1 ) || ( direction == HORIZONTAL && target.maxScrollH > 0 ) ) )
			{
				if ( val < 0 )
					val = 0;
				else if ( val > 100 )
					val = 100;
				adjustedHeight = Number( val ) * ( track.height / 100 );
			}
			thumb.height = Math.round( adjustedHeight );
			area.height = track.height - thumb.height;
		}
		
		/**
		 * 移动效果
		 */ /*private function set blur( on:Boolean ):void
		   {
		   if ( target != null && effect )
		   Tweener.addTween( target , { time: speed * 0.5 , blurFilter: { blurX: on ? 0 : 0 , blurY: on ? 2 : 0 , quality: 3 } , transition: ease } );
		 }*/
		
		private function onMouseWheel( e:MouseEvent ):void
		{
			setScrollRatio( scrollRatio - ( e.delta * thumb.height / ( 2 * Math.abs( e.delta ) * area.height ) ) );
			e.updateAfterEvent();
		}
		
		private function onTrackDown( e:MouseEvent ):void
		{
			setScrollRatio(( mouseY - thumb.height / 2 ) / area.height );
		}
		
		private function onThumbDown( e:MouseEvent ):void
		{
			offset = mouseY - thumb.y;
			stage.addEventListener( MouseEvent.MOUSE_UP , onThumbUp );
			stage.addEventListener( MouseEvent.MOUSE_MOVE , _onMouseMove );
		}
		
		private function onThumbUp( e:MouseEvent ):void
		{
			stage.removeEventListener( MouseEvent.MOUSE_UP , onThumbUp );
			stage.removeEventListener( MouseEvent.MOUSE_MOVE , _onMouseMove );
		}
		
		private function _onMouseMove( e:MouseEvent ):void
		{
			setScrollRatio(( mouseY - offset - area.y ) / area.height );
			e.updateAfterEvent();
		}
		
		private function onBtnUpDown( e:MouseEvent ):void
		{
			stage.addEventListener( MouseEvent.MOUSE_UP , onBtnUp );
			scrollSign = -1;
			onTimerTick();
			timerScroll.start();
		}
		
		private function onBtnDownDown( e:MouseEvent ):void
		{
			stage.addEventListener( MouseEvent.MOUSE_UP , onBtnUp );
			scrollSign = 1;
			onTimerTick();
			timerScroll.start();
		}
		
		private function onTimerTick( e:TimerEvent = null ):void
		{
			setScrollRatio( scrollRatio + ( scrollSign * _scrollIncrement / 100 ) );
		}
		
		private function onBtnUp( e:MouseEvent ):void
		{
			stage.removeEventListener( MouseEvent.MOUSE_UP , onBtnUp );
			timerScroll.stop();
		}
		
		private function onTargetContentChange( e:Event ):void
		{
			setSize( sizeRatio );
		}
		
		private function onScroll( e:Event ):void
		{
			
			if ( e.currentTarget == this )
			{
				target.removeEventListener( Event.SCROLL , onScroll );
				if ( direction == VERTICAL )
					target.scrollV = scrollRatio * ( target.maxScrollV - 1 ) + 1;
				else
					target.scrollH = scrollRatio * target.maxScrollH;
				target.addEventListener( Event.SCROLL , onScroll );
			}
			
			else
			{
				dispatcherToMute = this;
				scrollRatio = ( direction == VERTICAL ? ( target.scrollV - 1 ) / ( target.maxScrollV - 1 ) : target.scrollH / target.maxScrollH );
			}
		
		}
	
	}

}